
Imports storoomc
Imports storcore

Public Module storoom

    Public Const defaultConfigfile As String = "storoom.ini"
    Friend configfile As String = defaultConfigfile
    Friend WithEvents config As configMonitor = Nothing
    Friend slicemgr As storageInterface = Nothing
    Friend server As roomserver = Nothing
    Friend restart As Boolean = False

    Friend Sub startService()
        If config Is Nothing Then
            config = New configMonitor()
            If Not config.open(configfile) Then
                raiseError("failed to open configfile " + configfile + ", start shutdown" _
                            , errorHandle.errorType.exclamation)
                shutdown()
            Else
                If Not slicemgr Is Nothing AndAlso Not slicemgr.close() Then
                    raiseError("cannot close slicemgr_" + slicemgr.GetType().FullName, errorHandle.errorType.system)
                End If
                Dim seektype As String = Nothing
                seektype = config.parameter(Of String)(configNaming.storoom.name, _
                                                       configNaming.storoom.seektype, _
                                                       configNaming.storoom.defaultValue.seektype)
                distributingTM.register()
                If strsame(seektype, configNaming.storoom.seektypeDefinition.fixpoint, False) Then
                    slicemgr = New nodes_fixpoint()
#If RETIRED Then
                    If TypeOf slicemgr Is nodes_broadcast Then
                        If Not CType(slicemgr, nodes_broadcast).close() Then
                            raiseError("cannot close slicemgr{nodes_broadcast}.", errorHandle.errorType.system)
                        End If
                        slicemgr = Nothing
                    End If
                    If slicemgr Is Nothing Then
                        slicemgr = New nodes_fixpoint()
                    End If
                    CType(slicemgr, nodes_fixpoint).start()
#End If
                ElseIf strsame(seektype, configNaming.storoom.seektypeDefinition.redundance, False) Then
                    slicemgr = New nodes_redundance()
#If RETIRED Then
                    If TypeOf slicemgr Is nodes_fixpoint Then
                        If Not CType(slicemgr, nodes_fixpoint).close() Then
                            raiseError("cannot close slicemgr{nodes_fixpoint}.", errorHandle.errorType.system)
                        End If
                        slicemgr = Nothing
                    End If
                    If slicemgr Is Nothing Then
                        slicemgr = New nodes_broadcast()
                    End If
                    CType(slicemgr, nodes_broadcast).start()
#End If
                ElseIf strsame(seektype, configNaming.storoom.seektypeDefinition.redundance2, False) Then
                    slicemgr = New nodes_redundance2()
                ElseIf strsame(seektype, configNaming.storoom.seektypeDefinition.redundance3, False) Then
                    slicemgr = New nodes_redundance3()
                ElseIf strsame(seektype, configNaming.storoom.seektypeDefinition.hash, False) Then
                    slicemgr = New nodes_hash()
                ElseIf strsame(seektype, configNaming.storoom.seektypeDefinition.broadcast, False) Then
                    slicemgr = New nodes_broadcast()
                Else
                    raiseError(configNaming.storoom.seektype, " is not correctly set, use broadcast as default value.")
                    slicemgr = New nodes_broadcast()
                End If
                convertor.cast(Of storoomOper)(slicemgr).start()
                raiseError("seektype ", slicemgr.GetType().FullName())
                If server Is Nothing Then
                    server = New roomserver()
                End If
                server.start()
            End If
        End If
    End Sub

    Private Sub shutdownService()
        If Not server Is Nothing Then
            server.stop()
            server = Nothing
        End If
        If Not slicemgr Is Nothing Then
            slicemgr.close()
            slicemgr = Nothing
        End If
    End Sub

    Private Sub shutdown()
        shutdownService()
        finishmain()
    End Sub

    Private Sub monitor()
        registerConsoleExtHandle()

restart:
        While Not consoleExtSignal()
            If restart OrElse
               (Not slicemgr Is Nothing AndAlso slicemgr.health() AndAlso
                Not server Is Nothing AndAlso server.health()) Then
                sleep(1000)
            Else
                Exit While
            End If
        End While

        If Not consoleExtSignal() Then
            If slicemgr Is Nothing OrElse Not slicemgr.health() Then
                raiseError("slices engender an error, start shutdown.", errorHandle.errorType.exclamation)
            ElseIf server Is Nothing OrElse Not server.health() Then
                raiseError("server engender an error, start shutdown.", errorHandle.errorType.exclamation)
            Else
                raiseError("temporary slicemgr or server error, return to monitor.", errorHandle.errorType.exclamation)
                GoTo restart
            End If
        Else
            raiseError("terminating signal caught, start shutdown.")
        End If
    End Sub

    Public Sub unhandledException(ByVal ex As Exception)
        shutdown()
    End Sub

    Public Sub main(ByVal args() As String)
        startmain(AddressOf unhandledException)
        If args.Length > 0 Then
            configfile = args(0)
            raiseError("use argument0 " + configfile + " as config file, instead of default config file")
        End If
        timelimitOperation.disable()

        startService()
        monitor()
        shutdown()
    End Sub

    Private Sub config_ConfigChanged() Handles config.ConfigChanged
        restart = True
        shutdownService()
        startService()
        restart = False
    End Sub

    Private Sub config_ConfigfileDeleted() Handles config.ConfigfileDeleted
        If configDeletedOperation(configfile) Then
            shutdown()
        End If
    End Sub
End Module
